(import
  (except (rnrs base) let-values map error)
  (only (guile)
        lambda* λ
        command-line
        string-null?
        string-length)
  ;; PEG parsing
  (ice-9 peg)
  (ice-9 format)
  ;; list utils
  (prefix (srfi srfi-1) srfi-1:)
  ;; for unit testing forms
  (srfi srfi-64)
  ;; for list procedures
  (srfi srfi-1)
  (file-reader)
  (prefix (iter-utils) iter-util:)
  (prefix (peg-tree-utils) peg-utils:)
  ;; module under test
  (grammar))


(test-begin "grammar-test")

(test-group
 "grammar-basics"
 (test-assert "special-character-space-01"
   (peg-record? (match-pattern SPACE " ")))
 (test-assert "special-character-space-02"
   (not (peg-record? (match-pattern SPACE "\n"))))

 (test-assert "special-character-newline-01"
   (peg-record? (match-pattern NEWLINE "\n")))
 (test-assert "special-character-newline-02"
   (not (peg-record? (match-pattern NEWLINE "\r"))))

 (test-assert "special-character-attr-val-sep-01"
   (peg-record? (match-pattern ATTRIBUTE-VALUE-SEPARATOR ":")))
 (test-assert "special-character-attr-val-sep-02"
   (not (peg-record? (match-pattern ATTRIBUTE-VALUE-SEPARATOR ";"))))

 (test-assert "special-character-comment-start-01"
   (peg-record? (match-pattern COMMENT-STARTER "#")))
 (test-assert "special-character-comment-start-02"
   (not (peg-record? (match-pattern COMMENT-STARTER " "))))

 (test-assert "special-character-digit-01"
   (peg-record? (match-pattern DIGIT "4")))
 (test-assert "special-character-digit-02"
   (not (peg-utils:exhausting-match? DIGIT "0202")))
 (test-assert "special-character-digit-03"
   (not (peg-record? (match-pattern DIGIT "A"))))

 (test-assert "special-character-non-zero-digit-01"
   (reduce (λ (elem acc) (and acc elem))
           #t
           (map (λ (elem)
                  (peg-record?
                   (match-pattern NON-ZERO-DIGIT (number->string elem))))
                (iter-util:range 1 9 #:start-inclusive #t #:end-inclusive #t #:step 1))))
 (test-assert "special-character-non-zero-digit-02"
   (not (peg-record? (match-pattern NON-ZERO-DIGIT "0"))))

 (test-assert "special-character-whitespace-01"
   (reduce (λ (elem acc) (and acc elem))
           #t
           (map (λ (elem) (peg-record? (match-pattern WHITESPACE elem)))
                '(" " "\n" "\t" "\r"))))
 (test-assert "special-character-whitespace-02"
   (not (peg-record? (match-pattern WHITESPACE "_"))))

 (test-assert "special-character-whitespace-except-newline-01"
   (reduce (λ (elem acc) (and acc elem))
           #t
           (map (λ (elem) (peg-record? (match-pattern WHITESPACE-EXCEPT-NEWLINE elem)))
                '(" " "\t" "\r"))))
 (test-assert "special-character-whitespace-except-newline-02"
   (not (peg-record? (match-pattern WHITESPACE-EXCEPT-NEWLINE "\n")))))


(test-group
 "numbers"

 ;; ========
 ;; INTEGERS
 ;; ========
 (test-assert "special-string-integer-01"
   (peg-record? (match-pattern INTEGER "123")))
 (test-assert "special-string-integer-02"
   (peg-record? (match-pattern INTEGER "-123")))
 (test-assert "special-string-integer-03"
   (peg-record? (match-pattern INTEGER "0")))
 (test-assert "special-string-integer-04"
   (not (peg-utils:exhausting-match? INTEGER "01")))
 (test-assert "special-string-integer-05"
   (not (peg-record? (match-pattern INTEGER "-01"))))

 (test-assert "special-string-positive-integer-01"
   (peg-record? (match-pattern POSITIVE-INTEGER "123")))
 (test-assert "special-string-positive-integer-02"
   (not (peg-record? (match-pattern POSITIVE-INTEGER "-123"))))
 (test-assert "special-string-positive-integer-03"
   (peg-record? (match-pattern POSITIVE-INTEGER "0")))
 (test-assert "special-string-positive-integer-04"
   (not (peg-utils:exhausting-match? POSITIVE-INTEGER "01")))
 (test-assert "special-string-positive-integer-05"
   (not (peg-record? (match-pattern POSITIVE-INTEGER "-01"))))
 ;; =====================
 ;; SIMPLE POSITIVE FLOAT
 ;; =====================
 (test-assert "special-string-simple-positive-float-number-01"
   (peg-record?
    (match-pattern SIMPLE-POSITIVE-FLOAT-NUMBER "1.01212")))
 (test-assert "special-string-simple-positive-float-number-02"
   (peg-record?
    (match-pattern SIMPLE-POSITIVE-FLOAT-NUMBER "0.01212")))
 (test-assert "special-string-simple-positive-float-number-03"
   (peg-record?
    (match-pattern SIMPLE-POSITIVE-FLOAT-NUMBER "771.01212")))
 (test-assert "special-string-simple-positive-float-number-04"
   (peg-record?
    (match-pattern SIMPLE-POSITIVE-FLOAT-NUMBER "771.0000009")))
 (test-assert "special-string-simple-positive-float-number-05"
   (peg-record?
    (match-pattern SIMPLE-POSITIVE-FLOAT-NUMBER "771.00000000000000000000009")))
 (test-assert "special-string-simple-positive-float-number-06"
   (not
    (peg-record?
     (match-pattern SIMPLE-POSITIVE-FLOAT-NUMBER "1"))))
 (test-assert "special-string-simple-positive-float-number-07"
   (not
    (peg-record?
     (match-pattern SIMPLE-POSITIVE-FLOAT-NUMBER "2"))))
 (test-assert "special-string-simple-positive-float-number-08"
   (not
    (peg-record?
     (match-pattern SIMPLE-POSITIVE-FLOAT-NUMBER "3."))))
 (test-assert "special-string-simple-positive-float-number-09"
   (not
    (peg-record?
     (match-pattern SIMPLE-POSITIVE-FLOAT-NUMBER "13."))))

 ;; ============
 ;; SIMPLE FLOAT
 ;; ============
 (test-assert "special-string-simple-float-number-01"
   (peg-record?
    (match-pattern SIMPLE-FLOAT-NUMBER "1.01212")))
 (test-assert "special-string-simple-float-number-02"
   (peg-record?
    (match-pattern SIMPLE-FLOAT-NUMBER "0.01212")))
 (test-assert "special-string-simple-float-number-03"
   (peg-record?
    (match-pattern SIMPLE-FLOAT-NUMBER "771.01212")))
 (test-assert "special-string-simple-float-number-04"
   (peg-record?
    (match-pattern SIMPLE-FLOAT-NUMBER "771.0000009")))
 (test-assert "special-string-simple-float-number-05"
   (peg-record?
    (match-pattern SIMPLE-FLOAT-NUMBER "771.00000000000000000000009")))

 (test-assert "special-string-simple-float-number-06"
   (peg-record?
    (match-pattern SIMPLE-FLOAT-NUMBER "-1.01212")))
 (test-assert "special-string-simple-float-number-07"
   (peg-record?
    (match-pattern SIMPLE-FLOAT-NUMBER "-0.01212")))
 (test-assert "special-string-simple-float-number-08"
   (peg-record?
    (match-pattern SIMPLE-FLOAT-NUMBER "-771.01212")))
 (test-assert "special-string-simple-float-number-09"
   (peg-record?
    (match-pattern SIMPLE-FLOAT-NUMBER "-771.0000009")))
 (test-assert "special-string-simple-float-number-10"
   (peg-record?
    (match-pattern SIMPLE-FLOAT-NUMBER "-771.00000000000000000000009")))

 (test-assert "special-string-simple-float-number-11"
   (not
    (peg-record?
     (match-pattern SIMPLE-FLOAT-NUMBER "1"))))
 (test-assert "special-string-simple-float-number-12"
   (not
    (peg-record?
     (match-pattern SIMPLE-FLOAT-NUMBER "2"))))
 (test-assert "special-string-simple-float-number-13"
   (not
    (peg-record?
     (match-pattern SIMPLE-FLOAT-NUMBER "3."))))
 (test-assert "special-string-simple-float-number-14"
   (not
    (peg-record?
     (match-pattern SIMPLE-FLOAT-NUMBER "13."))))

 ;; ======
 ;; NUMBER
 ;; ======
 (test-assert "special-string-number-01"
   (peg-record? (match-pattern NUMBER "123")))
 (test-assert "special-string-number-02"
   (peg-record? (match-pattern NUMBER "-123")))
 (test-assert "special-string-number-03"
   (peg-record? (match-pattern NUMBER "0")))

 (test-assert "special-string-number-04"
   (not (peg-utils:exhausting-match? NUMBER "01")))

 (test-assert "special-string-integer-05"
   (not (peg-record? (match-pattern NUMBER "-01"))))

 (test-assert "special-string-number-01"
   (peg-record?
    (match-pattern NUMBER "1.01212")))
 (test-assert "special-string-number-02"
   (peg-record?
    (match-pattern NUMBER "0.01212")))
 (test-assert "special-string-number-03"
   (peg-record?
    (match-pattern NUMBER "771.01212")))
 (test-assert "special-string-number-04"
   (peg-record?
    (match-pattern NUMBER "771.0000009")))
 (test-assert "special-string-number-05"
   (peg-record?
    (match-pattern NUMBER "771.00000000000000000000009")))
 (test-assert "special-string-number-06"
   (peg-record?
    (match-pattern NUMBER "1")))
 (test-assert "special-string-number-07"
   (peg-record?
    (match-pattern NUMBER "2")))

 (test-assert "special-string-number-08"
   (peg-record?
    (match-pattern NUMBER "1.01212")))
 (test-assert "special-string-number-09"
   (peg-record?
    (match-pattern NUMBER "0.01212")))
 (test-assert "special-string-number-10"
   (peg-record?
    (match-pattern NUMBER "771.01212")))
 (test-assert "special-string-number-11"
   (peg-record?
    (match-pattern NUMBER "771.0000009")))
 (test-assert "special-string-number-12"
   (peg-record?
    (match-pattern NUMBER "771.00000000000000000000009")))

 (test-assert "special-string-number-13"
   (peg-record?
    (match-pattern NUMBER "-1.01212")))
 (test-assert "special-string-number-14"
   (peg-record?
    (match-pattern NUMBER "-0.01212")))
 (test-assert "special-string-number-15"
   (peg-record?
    (match-pattern NUMBER "-771.01212")))
 (test-assert "special-string-number-16"
   (peg-record?
    (match-pattern NUMBER "-771.0000009")))
 (test-assert "special-string-number-17"
   (peg-record?
    (match-pattern NUMBER "-771.00000000000000000000009")))

 (test-assert "special-string-number-18"
   (not (peg-utils:exhausting-match? NUMBER "13.")))

 ;; ==========
 ;; ACT NUMBER
 ;; ==========
 (test-assert "special-string-act-number-01"
   (peg-utils:exhausting-match? ACT-NUMBER "0"))

 (test-assert "special-string-act-number-02"
   (peg-utils:exhausting-match? ACT-NUMBER "10"))

 (test-assert "special-string-act-number-03"
   (peg-utils:exhausting-match? ACT-NUMBER "20"))

 (test-assert "special-string-act-number-04"
   (peg-utils:exhausting-match? ACT-NUMBER "30"))

 (test-assert "special-string-act-number-05"
   (peg-utils:exhausting-match? ACT-NUMBER "40"))

 (test-assert "special-string-act-number-06"
   (peg-utils:exhausting-match? ACT-NUMBER "50"))

 (test-assert "special-string-act-number-07"
   (peg-utils:exhausting-match? ACT-NUMBER "60"))

 (test-assert "special-string-act-number-08"
   (not
    (peg-record?
     (match-pattern ACT-NUMBER "55"))))

 (test-assert "special-string-act-number-09"
   (not
    (peg-record?
     (match-pattern ACT-NUMBER "-10"))))

 (test-assert "special-string-act-number-10"
   (not
    (peg-utils:exhausting-match? ACT-NUMBER "100")))

 (test-assert "special-string-act-number-11"
   (not
    (peg-record?
     (match-pattern ACT-NUMBER "1.23"))))

 (test-assert "special-string-act-number-12"
   (not
    (peg-record?
     (match-pattern ACT-NUMBER "-0.23")))))


(test-group
 "other strings"

 (test-assert "special-string-non-newline-containing-string-01"
   (peg-record? (match-pattern NON-NEWLINE-CONTAINING-STRING "452445zqi\t4bm2zßv ß2 t3wa #\t\r")))
 (test-assert "special-string-non-newline-containing-string-02"
   (peg-record? (match-pattern NON-NEWLINE-CONTAINING-STRING "  dsfhtshtG")))
 (test-assert "special-string-non-newline-containing-string-03"
   (peg-record? (match-pattern NON-NEWLINE-CONTAINING-STRING "  dsf\"$/&\"!)!&/§)§&h'''tshtG")))

 (test-assert "special-string-non-newline-containing-string-04"
   (not (peg-utils:exhausting-match? NON-NEWLINE-CONTAINING-STRING "  \n")))
 (test-assert "special-string-non-newline-containing-string-05"
   (not (peg-record? (match-pattern NON-NEWLINE-CONTAINING-STRING "\nsadasdasd"))))
 (test-assert "special-string-non-newline-containing-string-06"
   (not (peg-record? (match-pattern NON-NEWLINE-CONTAINING-STRING "\nsadas  asdsad\n"))))

 (test-assert "special-string-non-whitespace-containing-string-01"
   (peg-record? (match-pattern NON-WHITESPACE-CONTAINING-STRING "452445zqi4bm2zßvß2t3wa#")))
 (test-assert "special-string-non-whitespace-containing-string-02"
   (peg-record? (match-pattern NON-WHITESPACE-CONTAINING-STRING "dsfhtshtG")))

 (test-assert "special-string-non-whitespace-containing-string-03"
   (not (peg-utils:exhausting-match? NON-WHITESPACE-CONTAINING-STRING " asdasd")))
 (test-assert "special-string-non-whitespace-containing-string-04"
   (not (peg-utils:exhausting-match? NON-WHITESPACE-CONTAINING-STRING "asd asd")))
 (test-assert "special-string-non-whitespace-containing-string-05"
   (not (peg-utils:exhausting-match? NON-WHITESPACE-CONTAINING-STRING "asd  asd")))
 (test-assert "special-string-non-whitespace-containing-string-06"
   (not (peg-utils:exhausting-match? NON-WHITESPACE-CONTAINING-STRING "asdasd ")))

 (test-assert "special-string-non-whitespace-containing-string-07"
   (not (peg-utils:exhausting-match? NON-WHITESPACE-CONTAINING-STRING "\tasdasd")))
 (test-assert "special-string-non-whitespace-containing-string-08"
   (not (peg-utils:exhausting-match? NON-WHITESPACE-CONTAINING-STRING "asd\tasd")))
 (test-assert "special-string-non-whitespace-containing-string-09"
   (not (peg-utils:exhausting-match? NON-WHITESPACE-CONTAINING-STRING "asd\t\tasd")))
 (test-assert "special-string-non-whitespace-containing-string-10"
   (not (peg-utils:exhausting-match? NON-WHITESPACE-CONTAINING-STRING "asdasd\t")))

 (test-assert "special-string-non-whitespace-containing-string-11"
   (not (peg-utils:exhausting-match? NON-WHITESPACE-CONTAINING-STRING "\rasadasdsdasd")))
 (test-assert "special-string-non-whitespace-containing-string-12"
   (not (peg-utils:exhausting-match? NON-WHITESPACE-CONTAINING-STRING "asd\rztjuzasd")))
 (test-assert "special-string-non-whitespace-containing-string-13"
   (not (peg-utils:exhausting-match? NON-WHITESPACE-CONTAINING-STRING "asd\r\ravnnmiu.sad.-sd")))
 (test-assert "special-string-non-whitespace-containing-string-14"
   (not (peg-utils:exhausting-match? NON-WHITESPACE-CONTAINING-STRING "asdasd\r\n")))

 (test-assert "special-string-non-whitespace-containing-string-15"
   (not (peg-utils:exhausting-match? NON-WHITESPACE-CONTAINING-STRING "\nasadasdsdasd")))
 (test-assert "special-string-non-whitespace-containing-string-16"
   (not (peg-utils:exhausting-match? NON-WHITESPACE-CONTAINING-STRING "asd\nztjuzasd")))
 (test-assert "special-string-non-whitespace-containing-string-17"
   (not (peg-utils:exhausting-match? NON-WHITESPACE-CONTAINING-STRING "asd\n\navnnmiu.sad.-sd")))
 (test-assert "special-string-non-whitespace-containing-string-18"
   (not (peg-utils:exhausting-match? NON-WHITESPACE-CONTAINING-STRING "asdasd\n")))

 ;; currently FILENAME, and COMMENT-TEXT are the same as NON-NEWLINE-CONTAINING-STRING, so not it testing here.
 ;; currently ENTITIY-COMMENT-TEXT is the same as NON-WHITESPACE-CONTAINING-STRING, so not it testing here.

 (test-assert "special-string-ignored-whitespace-01"
   (peg-utils:exhausting-match? IGNORED-WHITESPACE "  \t\n\r"))

 (test-assert "special-string-ignored-whitespace-02"
   (not (peg-utils:exhausting-match? IGNORED-WHITESPACE "  \taaa\n\r")))

 (test-assert "special-string-ignored-whitespace-except-newline-01"
   (peg-utils:exhausting-match? IGNORED-WHITESPACE "  \t\r"))

 (test-assert "special-string-ignored-whitespace-except-newline-02"
   (not (peg-utils:exhausting-match? IGNORED-WHITESPACE "  \taaa\r"))))


(test-group
 "tags"

 (test-assert "stage-tag-01"
   (peg-utils:exhausting-match? STAGE-TAG "<stage>"))

 (test-assert "stage-tag-02"
   (not (peg-record? (match-pattern STAGE-TAG "<stage_end>"))))

 (test-assert "stage-end-tag-01"
   (peg-utils:exhausting-match? STAGE-END-TAG "<stage_end>"))

 (test-assert "stage-end-tag-02"
   (not (peg-record? (match-pattern STAGE-END-TAG "<stage_ende>"))))

 (test-assert "phase-tag-01"
   (peg-utils:exhausting-match? PHASE-TAG "<phase>"))

 (test-assert "phase-tag-02"
   (not (peg-record? (match-pattern PHASE-TAG "<phase_end>"))))

 (test-assert "phase-end-tag-01"
   (peg-utils:exhausting-match? PHASE-END-TAG "<phase_end>"))

 (test-assert "phase-end-tag-02"
   (not (peg-record? (match-pattern PHASE-END-TAG "<phase_ende>"))))

 (test-assert "boss-tag-01"
   (peg-utils:exhausting-match? BOSS-TAG "<boss>"))

 (test-assert "boss-tag-02"
   (not (peg-record? (match-pattern BOSS-TAG "<bossy>"))))

 (test-assert "soldier-tag-01"
   (peg-utils:exhausting-match? SOLDIER-TAG "<soldier>"))

 (test-assert "soldier-tag-02"
   (not (peg-record? (match-pattern SOLDIER-TAG "<soldiery>"))))

 (test-assert "end-tag-01"
   (peg-utils:exhausting-match? END-TAG "<end>"))

 (test-assert "end-tag-02"
   (not (peg-record? (match-pattern END-TAG "<endy>")))))


;; (test-group
;;  "attribute-names"

;;  ;; Those are really just plain strings, not testing here -- remind my future
;;  ;; self of having written these words please.
;;  )

(test-group
 "attributes"
 (test-assert "id-attribute-01"
   (peg-utils:exhausting-match? ID-ATTRIBUTE "id:   \t 13"))

 (test-assert "id-attribute-02"
   (not (peg-record? (match-pattern ID-ATTRIBUTE "id: hello"))))

 (test-assert "bound-attribute-01"
   (peg-utils:exhausting-match? BOUND-ATTRIBUTE "bound:   \t 1500"))

 (test-assert "bound-attribute-02"
   (not (peg-record? (match-pattern BOUND-ATTRIBUTE "bound:   \t -1500"))))

 (test-assert "bound-attribute-03"
   (not (peg-utils:exhausting-match? BOUND-ATTRIBUTE "bound:   \t 1500x")))

 (test-assert "music-attribute-01"
   (peg-utils:exhausting-match? MUSIC-ATTRIBUTE "music: bgm\\stage1.wma"))

 (test-assert "music-attribute-02"
   (peg-utils:exhausting-match? MUSIC-ATTRIBUTE "music: \t  bgm\\stage1.wma"))

 (test-assert "music-attribute-03"
   (not (peg-utils:exhausting-match? MUSIC-ATTRIBUTE "music: \nbgm\\stage1.wma")))

 (test-assert "x-coord-attribute-01"
   (peg-utils:exhausting-match? X-COORD-ATTRIBUTE "x: 900"))

 (test-assert "x-coord-attribute-02"
   (peg-utils:exhausting-match? X-COORD-ATTRIBUTE "x: 1900"))

 (test-assert "x-coord-attribute-03"
   (not (peg-utils:exhausting-match? X-COORD-ATTRIBUTE "x: 0900")))

 (test-assert "x-coord-attribute-04"
   (not (peg-record? (match-pattern X-COORD-ATTRIBUTE "x: hello"))))

 (test-assert "y-coord-attribute-01"
   (peg-utils:exhausting-match? Y-COORD-ATTRIBUTE "y: 900"))

 (test-assert "y-coord-attribute-02"
   (peg-utils:exhausting-match? Y-COORD-ATTRIBUTE "y: 1900"))

 (test-assert "y-coord-attribute-03"
   (not (peg-utils:exhausting-match? Y-COORD-ATTRIBUTE "y: 0900")))

 (test-assert "y-coord-attribute-04"
   (not (peg-record? (match-pattern Y-COORD-ATTRIBUTE "y: hello"))))

 (test-assert "hp-attribute-01"
   (peg-utils:exhausting-match? HP-ATTRIBUTE "hp: 10"))

 (test-assert "hp-attribute-02"
   (peg-utils:exhausting-match? HP-ATTRIBUTE "hp: 19999"))

 (test-assert "ratio-attribute-01"
   (peg-utils:exhausting-match? RATIO-ATTRIBUTE "ratio: 0.3"))

 (test-assert "ratio-attribute-02"
   (peg-utils:exhausting-match? RATIO-ATTRIBUTE "ratio: 0.7"))

 (test-assert "ratio-attribute-03"
   (peg-utils:exhausting-match? RATIO-ATTRIBUTE "ratio: 1.2"))

 (test-assert "ratio-attribute-04"
   (peg-utils:exhausting-match? RATIO-ATTRIBUTE "ratio: .4"))

 (test-assert "ratio-attribute-01"
   (peg-utils:exhausting-match? RATIO-ATTRIBUTE "ratio:\t 0.3"))

 (test-assert "ratio-attribute-02"
   (peg-utils:exhausting-match? RATIO-ATTRIBUTE "ratio:\t 0.7"))

 (test-assert "ratio-attribute-03"
   (peg-utils:exhausting-match? RATIO-ATTRIBUTE "ratio: \t1.2"))

 (test-assert "ratio-attribute-04"
   (peg-utils:exhausting-match? RATIO-ATTRIBUTE "ratio: \t .4"))

 (test-assert "ratio-attribute-05"
   (not (peg-record? (match-pattern RATIO-ATTRIBUTE "ratio: -0.3"))))

 (test-assert "ratio-attribute-06"
   (not (peg-record? (match-pattern RATIO-ATTRIBUTE "ratio: -0.7"))))

 (test-assert "ratio-attribute-07"
   (not (peg-record? (match-pattern RATIO-ATTRIBUTE "ratio: -1.2"))))

 (test-assert "ratio-attribute-08"
   (not (peg-record? (match-pattern RATIO-ATTRIBUTE "ratio: -.4"))))

 (test-assert "times-attribute-01"
   (peg-utils:exhausting-match? TIMES-ATTRIBUTE "times: 3"))

 (test-assert "times-attribute-02"
   (peg-utils:exhausting-match? TIMES-ATTRIBUTE "times:   3"))

 (test-assert "times-attribute-03"
   (peg-utils:exhausting-match? TIMES-ATTRIBUTE "times:\t3"))

 (test-assert "times-attribute-04"
   (peg-utils:exhausting-match? TIMES-ATTRIBUTE "times:\t20"))

 (test-assert "times-attribute-05"
   (not (peg-record? (match-pattern TIMES-ATTRIBUTE "times: -4"))))

 (test-assert "times-attribute-06"
   (not (peg-record? (match-pattern TIMES-ATTRIBUTE "times:\n-4"))))

 (test-assert "reserve-attribute-01"
   (peg-utils:exhausting-match? RESERVE-ATTRIBUTE "reserve: 2"))

 (test-assert "reserve-attribute-02"
   (peg-utils:exhausting-match? RESERVE-ATTRIBUTE "reserve:              2"))

 (test-assert "reserve-attribute-03"
   (peg-utils:exhausting-match? RESERVE-ATTRIBUTE "reserve:     \t\t\r         2"))

 (test-assert "reserve-attribute-04"
   (not (peg-utils:exhausting-match? RESERVE-ATTRIBUTE "reserve:\n 4.0")))

 (test-assert "reserve-attribute-05"
   (not (peg-utils:exhausting-match? RESERVE-ATTRIBUTE "reserve:    1.2")))

 (test-assert "reserve-attribute-06"
   (not (peg-record? (match-pattern RESERVE-ATTRIBUTE "reserve:    -1.2"))))

 (test-assert "reserve-attribute-07"
   (not (peg-record? (match-pattern RESERVE-ATTRIBUTE "reserve: -3"))))

 (test-assert "reserve-attribute-08"
   (not (peg-record? (match-pattern RESERVE-ATTRIBUTE "reserve: -0.002"))))

 ;; JOIN
 (test-assert "join-attribute-01"
   (peg-utils:exhausting-match? JOIN-ATTRIBUTE "join: 200"))

 (test-assert "join-attribute-02"
   (peg-utils:exhausting-match? JOIN-ATTRIBUTE "join:200"))

 (test-assert "join-attribute-03"
   (not (peg-record? (match-pattern JOIN-ATTRIBUTE "join: -200"))))

 (test-assert "join-attribute-04"
   (not (peg-utils:exhausting-match? JOIN-ATTRIBUTE "join: 0.23")))

 (test-assert "join-attribute-05"
   (not (peg-record? (match-pattern JOIN-ATTRIBUTE "join: -0.23"))))

 ;; JOIN RESERVE
 (test-assert "join-reserve-attribute-01"
   (peg-utils:exhausting-match? JOIN-RESERVE-ATTRIBUTE "join_reserve: 2"))

 (test-assert "join-reserve-attribute-02"
   ;; Should 0 be allowed?
   (peg-utils:exhausting-match? JOIN-RESERVE-ATTRIBUTE "join_reserve: 0"))

 (test-assert "join-reserve-attribute-03"
   ;; Should 0 be allowed?
   (not (peg-utils:exhausting-match? JOIN-RESERVE-ATTRIBUTE "join_reserve: 1.3")))

 (test-assert "join-reserve-attribute-04"
   (not (peg-record? (match-pattern JOIN-RESERVE-ATTRIBUTE "join_reserve: -1.3"))))

 (test-assert "join-reserve-attribute-05"
   (not (peg-record? (match-pattern JOIN-RESERVE-ATTRIBUTE "join_reserve: -4"))))

 ;; ACT
 (test-assert "act-attribute-01"
   (not (peg-record? (match-pattern ACT-ATTRIBUTE "act: -10"))))
 (test-assert "act-attribute-02"
   (not (peg-record? (match-pattern ACT-ATTRIBUTE "act: 5"))))
 (test-assert "act-attribute-03"
   (peg-utils:exhausting-match? ACT-ATTRIBUTE "act: 0"))
 (test-assert "act-attribute-04"
   (peg-utils:exhausting-match? ACT-ATTRIBUTE "act: 10"))
 (test-assert "act-attribute-05"
   (peg-utils:exhausting-match? ACT-ATTRIBUTE "act: 20"))
 (test-assert "act-attribute-06"
   (peg-utils:exhausting-match? ACT-ATTRIBUTE "act: 30"))
 (test-assert "act-attribute-07"
   (peg-utils:exhausting-match? ACT-ATTRIBUTE "act: 40"))
 (test-assert "act-attribute-08"
   (peg-utils:exhausting-match? ACT-ATTRIBUTE "act: 50"))
 (test-assert "act-attribute-09"
   (peg-utils:exhausting-match? ACT-ATTRIBUTE "act: 60")))


(test-group
 "comment-tests"
 (test-assert "comment-01"
   (peg-utils:exhausting-match? COMMENT "# daetfzjega fsudzg \t sdgfs"))

 (test-assert "comment-02"
   (peg-utils:exhausting-match? COMMENT "# daetfzjega fsudzg \t sdgfs#"))

 (test-assert "comment-03"
   (peg-utils:exhausting-match? COMMENT "# daetfzjega fsudzg \t sdgfs #asdasd"))

 (test-assert "comment-04"
   (peg-utils:exhausting-match? COMMENT "#daetfzjega fsudzg \t sdgfs # asdasd"))

 (test-assert "comment-05"
   (not (peg-utils:exhausting-match? COMMENT "#daetfzjega fsudzg \t sdgfs # asdasd\n id: 123"))))


(test-group
 "entity-comment-tests"

 (test-assert "entity-comment-01"
   (peg-utils:exhausting-match? ENTITY-COMMENT "#this-is-a-comment!"))

 (test-assert "entity-comment-02"
   (peg-utils:exhausting-match? ENTITY-COMMENT "#milk"))

 (test-assert "entity-comment-03"
   (peg-utils:exhausting-match? ENTITY-COMMENT "#beer"))

 (test-assert "entity-comment-04"
   (not
    (peg-record?
     (match-pattern ENTITY-COMMENT "# daetfzjegafsudzg"))))

 (test-assert "entity-comment-05"
   (not
    (peg-record?
     (match-pattern ENTITY-COMMENT "# daetfzj egafsudzg"))))

 (test-assert "entity-comment-06"
   (not
    (peg-utils:exhausting-match? ENTITY-COMMENT "#daetfzjegafsudzg "))))


(test-group
 "music-switch-tests"

 (test-assert "music-switch-01"
   (peg-utils:exhausting-match? MUSIC-SWITCH "music: bgm\\stage5.wma"))

 (test-assert "music-switch-02"
   (peg-utils:exhausting-match? MUSIC-SWITCH "music:bgm\\stage5.wma"))

 (test-assert "music-switch-03"
   (not
    (peg-utils:exhausting-match? MUSIC-SWITCH "music: bgm\\\nstage5.wma"))))


(test-group
 "entity-attributes-tests"

 (test-assert "entity-attributes-01"
   (peg-utils:exhausting-match? ENTITY-ATTRIBUTE "id: 300"))

 (test-assert "entity-attributes-02"
   (peg-utils:exhausting-match? ENTITY-ATTRIBUTE "x: 900"))

 (test-assert "entity-attributes-03"
   (peg-utils:exhausting-match? ENTITY-ATTRIBUTE "y: 0"))

 (test-assert "entity-attributes-04"
   (peg-utils:exhausting-match? ENTITY-ATTRIBUTE "hp: 200"))

 (test-assert "entity-attributes-05"
   (peg-utils:exhausting-match? ENTITY-ATTRIBUTE "ratio: 0.2"))

 (test-assert "entity-attributes-06"
   (peg-utils:exhausting-match? ENTITY-ATTRIBUTE "times: 3"))

 (test-assert "entity-attributes-07"
   (peg-utils:exhausting-match? ENTITY-ATTRIBUTE "reserve: 20"))

 (test-assert "entity-attributes-08"
   (peg-utils:exhausting-match? ENTITY-ATTRIBUTE "join: 150"))

 (test-assert "entity-attributes-09"
   (peg-utils:exhausting-match? ENTITY-ATTRIBUTE "join_reserve: 3"))

 (test-assert "entity-attributes-10"
   (peg-utils:exhausting-match? ENTITY-ATTRIBUTE "act: 10"))

 (test-assert "entity-attributes-11"
   (peg-utils:exhausting-match? ENTITY-ATTRIBUTE "<soldier>"))

 (test-assert "entity-attributes-12"
   (peg-utils:exhausting-match? ENTITY-ATTRIBUTE "<boss>"))

 (test-assert "entity-attributes-13"
   (peg-utils:exhausting-match? ENTITY-ATTRIBUTE "#milk"))

 (test-assert "entity-attributes-13"
   (peg-utils:exhausting-match? ENTITY-ATTRIBUTE "#beer")))


;; ENTITY
(test-group
 "entity-tests"
 (test-assert "entity-01-milk"
   (peg-utils:exhausting-match? ENTITY "id: 122  x: 300  #milk"))
 (test-assert "entity-02-milk-ratio"
   (peg-utils:exhausting-match? ENTITY "id: 122  x: 300  #milk  ratio: .7"))

 (test-assert "entity-03-beer"
   (peg-utils:exhausting-match? ENTITY "id: 123  x: 300  #beer"))
 (test-assert "entity-04-beer-ratio"
   (peg-utils:exhausting-match? ENTITY "id: 123  x: 300  #beer  ratio: .7"))

 (test-assert "entity-05-act"
   (peg-utils:exhausting-match? ENTITY "id: 300 hp: 100 act: 40 x: 900"))
 (test-assert "entity-06-act-with-reserve"
   (peg-utils:exhausting-match? ENTITY "id: 300 hp: 100 act: 50 x: 900 reserve: 5"))

 (test-assert "entity-07-random-ah-ub"
   (peg-utils:exhausting-match? ENTITY "id: 3000 hp: 50  times: 3  ratio: 1"))

 (test-assert "entity-08-soldier"
   (peg-utils:exhausting-match? ENTITY "id: 3000 hp: 50  ratio: 0.7     <soldier>"))
 (test-assert "entity-09-soldier-times"
   (peg-utils:exhausting-match? ENTITY "id: 3000 hp: 50  ratio: 0.7 <soldier> times: 7"))
 (test-assert "entity-10-soldier-times"
   (peg-utils:exhausting-match? ENTITY "id: 1000  hp: 200 times: 2 ratio: .3 <boss>"))

 (test-assert "entity-11"
   (peg-utils:exhausting-match? ENTITY "id: 34 hp: 100  times: 3"))
 (test-assert "entity-12"
   (peg-utils:exhausting-match? ENTITY "id: 34 hp: 100  times: 3  ratio: .5"))

 (test-assert "entity-13"
   (peg-utils:exhausting-match? ENTITY "id: 1000  hp: 250 times: 3 <boss>"))
 (test-assert "entity-14"
   (peg-utils:exhausting-match? ENTITY "id: 1000  hp: 250 ratio: .3 <boss>"))
 (test-assert "entity-15"
   (peg-utils:exhausting-match? ENTITY "id: 52  hp: 1200 <boss>"))
 (test-assert "entity-16"
   (peg-utils:exhausting-match? ENTITY "id: 51  hp: 1200 <boss>")))


;; PHASE-ENTITIES
(test-group
 "phase-entities-tests"
 (test-assert "phase-entities-survival-stage-000"
   (peg-utils:exhausting-match? PHASE-ENTITIES "id: 122  x: 100  #milk  ratio: 1
                id: 30 hp: 50  times: 1
                id: 30 hp: 50  times: 1  ratio: 0.7
                id: 30 hp: 50  times: 1  ratio: 0.3"))

 (test-assert "phase-entities-survival-stage-001"
   (peg-utils:exhausting-match? PHASE-ENTITIES "id: 30 hp: 50  times: 1
                id: 31 hp: 50  times: 1
                id: 30 hp: 50  times: 1  ratio: 0.7
                id: 31 hp: 50  times: 1  ratio: 0.3"))

 (test-assert "phase-entities-survival-stage-002"
   (peg-utils:exhausting-match? PHASE-ENTITIES "id: 122  x: 100  #milk
                id: 122  x: 100  #milk  ratio: 0.5
                id: 33  hp: 150 <boss>
                id: 33  hp: 150 ratio: .3 <boss>
                id: 3000 hp: 50  ratio: 0.7     <soldier>
                id: 3000 hp: 50  ratio: 0.3     <soldier>"))

 (test-assert "phase-entities-survival-stage-003"
   (peg-utils:exhausting-match? PHASE-ENTITIES "id: 32  hp: 200 <boss>
                id: 32  hp: 200 ratio: .3 <boss>
                id: 3000 hp: 50  ratio: 0.7     <soldier>
                id: 3000 hp: 50  ratio: 0.3     <soldier>"))

 (test-assert "phase-entities-survival-stage-004"
   (peg-utils:exhausting-match? PHASE-ENTITIES "id: 122  x: 100  #milk
                id: 122  x: 100  #milk  ratio: 0.5
                id: 1000  hp: 250 times: 3 <boss>
                id: 1000  hp: 250 ratio: .3 <boss>
                id: 3000 hp: 50  ratio: 0.7     <soldier>
                id: 3000 hp: 50  ratio: 0.3     <soldier>"))

 (test-assert "phase-entities-survival-stage-005"
   (peg-utils:exhausting-match? PHASE-ENTITIES "id: 122  x: 100  #milk
                id: 122  x: 100  #milk  ratio: 0.5
                id: 1000  hp: 250 times: 3 <boss>
                id: 1000  hp: 250 times: 2 ratio: .3 <boss>
                id: 3000 hp: 50  ratio: 0.7     <soldier>
                id: 3000 hp: 50  ratio: 0.3     <soldier>"))

 (test-assert "phase-entities-survival-stage-006"
   (peg-utils:exhausting-match? PHASE-ENTITIES "id: 122  x: 100  #milk
                id: 122  x: 100  #milk  ratio: 0.5
                id: 1000  hp: 250 times: 4 <boss>
                id: 1000  hp: 200 times: 2 ratio: .3 <boss>
                id: 3000 hp: 50  ratio: 0.7     <soldier>
                id: 3000 hp: 50  ratio: 0.3     <soldier>"))

 (test-assert "phase-entities-survival-stage-007"
   (peg-utils:exhausting-match? PHASE-ENTITIES "id: 122  x: 100  #milk
                id: 122  x: 100  #milk  ratio: 0.5
                id: 38  hp: 400 <boss>
                id: 37  hp: 200 ratio: 0.3 <soldier>
                id: 39 hp: 200  ratio: 0.7     <soldier>
                id: 39 hp: 200  ratio: 0.3     <soldier>"))

 (test-assert "phase-entities-survival-stage-008"
   (peg-utils:exhausting-match? PHASE-ENTITIES "id: 122  x: 100  #milk
                id: 122  x: 100  #milk  ratio: 0.5
                id: 50  hp: 400 <boss>
                id: 1000  hp: 250 ratio: 0.3 <soldier>
                id: 35 hp: 200  ratio: 0.7     <soldier>
                id: 35 hp: 200  ratio: 0.3     <soldier>"))

 (test-assert "phase-entities-survival-stage-009"
   (peg-utils:exhausting-match? PHASE-ENTITIES "id: 122  x: 100  #milk
                id: 122  x: 100  #milk  ratio: 0.5
                id: 51  hp: 500 <boss>
                id: 1000  hp: 250 ratio: 0.3 <soldier>
                id: 34 hp: 100  ratio: 0.7     <soldier>
                id: 34 hp: 100  ratio: 0.3     <soldier>"))

 (test-assert "phase-entities-survival-stage-010"
   (peg-utils:exhausting-match? PHASE-ENTITIES "id: 122  x: 100  #milk
                id: 122  x: 100  #milk  ratio: 0.5
                id: 52  hp: 600 <boss>
                id: 1000  hp: 250 ratio: 0.3 <soldier>
                id: 37 hp: 200  ratio: 0.7     <soldier>
                id: 37 hp: 200  ratio: 0.3     <soldier>"))

 ;; music attribute is not part of phase entities
 (test-assert "phase-entities-001"
   (not
    (peg-record?
     (match-pattern PHASE-ENTITIES "music: bgm\\boss1.wma
                id: 122  x: 100  #milk
                id: 122  x: 100  #milk  ratio: 0.5
                id: 38  hp: 400 <boss>
                id: 37  hp: 200 ratio: 0.3 <soldier>
                id: 39 hp: 200  ratio: 0.7     <soldier>
                id: 39 hp: 200  ratio: 0.3     <soldier>")))))


;; SURVIVAL STAGE
(test-group
 "survival-phases-tests"

 (test-assert "phase-survival-stage-followed-by-whitespace"
   (not
    (peg-utils:exhausting-match? PHASE
                                 "<phase> bound: 1500  # phase 0   bandit
                music: bgm\\stage4.wma
                id: 122  x: 100  #milk  ratio: 1
                id: 30 hp: 50  times: 1
                id: 30 hp: 50  times: 1  ratio: 0.7
                id: 30 hp: 50  times: 1  ratio: 0.3
        <phase_end>
    \t")))

 (let ([max-index-phases 99])
   (let iter ([phase-ind 0])
     (let* ([formatted-ind (format #f "~3,'0d" phase-ind)]
            [phase-text
             (string-trim-right
              (get-string-from-file
               (string-append "data/survival-stages/" formatted-ind ".txt"))
              (λ (c) (char=? c #\newline)))])
       (cond
        [(< phase-ind max-index-phases)
         (test-assert (string-append "all-survival-phases-" formatted-ind)
           (peg-utils:exhausting-match? PHASE phase-text))
         (iter (+ phase-ind 1))]
        [else
         (test-assert (string-append "all-survival-phases-" formatted-ind)
           (peg-utils:exhausting-match? PHASE phase-text))]))))

 (test-assert "survival-stage-phases-01"
   (peg-utils:exhausting-match?
    SURVIVAL-STAGE-PHASES
    (string-trim-right (get-string-from-file "data/survival-stages/all-phases.txt")
                       (λ (c) (char=? c #\newline))))))


(test-group
 "survival-stage"
 (test-assert "survival-stage"
   (peg-utils:exhausting-match?
    SURVIVAL-STAGE
    (string-trim-right (get-string-from-file "data/survival-stages/survival-stage.txt")
                       (λ (c) (char=? c #\newline))))))


(test-group
 "normal-stage"

 (test-assert "normal-stages-01"
   (peg-utils:exhausting-match?
    NORMAL-STAGE
    (string-trim-right (get-string-from-file "data/normal-stages/stage-1-1.txt")
                       (λ (c) (char=? c #\newline)))))

 (test-assert "normal-stages-02"
   (peg-utils:exhausting-match?
    NORMAL-STAGE
    (string-trim-right (get-string-from-file "data/normal-stages/stage-1-2.txt")
                       (λ (c) (char=? c #\newline)))))

 (test-assert "normal-stages-03"
   (peg-utils:exhausting-match?
    NORMAL-STAGE
    (string-trim-right (get-string-from-file "data/normal-stages/stage-1-3.txt")
                       (λ (c) (char=? c #\newline)))))

 (test-assert "normal-stages-04"
   (peg-utils:exhausting-match?
    NORMAL-STAGE
    (string-trim-right (get-string-from-file "data/normal-stages/stage-1-4.txt")
                       (λ (c) (char=? c #\newline)))))

 (test-assert "normal-stages-05"
   (peg-utils:exhausting-match?
    NORMAL-STAGE
    (string-trim-right (get-string-from-file "data/normal-stages/stage-1-5.txt")
                       (λ (c) (char=? c #\newline)))))

 (test-assert "normal-stages-06"
   (peg-utils:exhausting-match?
    NORMAL-STAGE
    (string-trim-right (get-string-from-file "data/normal-stages/stage-2-1.txt")
                       (λ (c) (char=? c #\newline)))))

 (test-assert "normal-stages-07"
   (peg-utils:exhausting-match?
    NORMAL-STAGE
    (string-trim-right (get-string-from-file "data/normal-stages/stage-2-2.txt")
                       (λ (c) (char=? c #\newline)))))

 (test-assert "normal-stages-08"
   (peg-utils:exhausting-match?
    NORMAL-STAGE
    (string-trim-right (get-string-from-file "data/normal-stages/stage-2-3.txt")
                       (λ (c) (char=? c #\newline)))))

 (test-assert "normal-stages-09"
   (peg-utils:exhausting-match?
    NORMAL-STAGE
    (string-trim-right (get-string-from-file "data/normal-stages/stage-2-4.txt")
                       (λ (c) (char=? c #\newline)))))

 (test-assert "normal-stages-10"
   (peg-utils:exhausting-match?
    NORMAL-STAGE
    (string-trim-right (get-string-from-file "data/normal-stages/stage-2-5.txt")
                       (λ (c) (char=? c #\newline)))))

 (test-assert "normal-stages-11"
   (peg-utils:exhausting-match?
    NORMAL-STAGE
    (string-trim-right (get-string-from-file "data/normal-stages/stage-3-1.txt")
                       (λ (c) (char=? c #\newline)))))

 (test-assert "normal-stages-12"
   (peg-utils:exhausting-match?
    NORMAL-STAGE
    (string-trim-right (get-string-from-file "data/normal-stages/stage-3-2.txt")
                       (λ (c) (char=? c #\newline)))))

 (test-assert "normal-stages-13"
   (peg-utils:exhausting-match?
    NORMAL-STAGE
    (string-trim-right (get-string-from-file "data/normal-stages/stage-3-3.txt")
                       (λ (c) (char=? c #\newline)))))

 (test-assert "normal-stages-14"
   (peg-utils:exhausting-match?
    NORMAL-STAGE
    (string-trim-right (get-string-from-file "data/normal-stages/stage-3-4.txt")
                       (λ (c) (char=? c #\newline)))))

 (test-assert "normal-stages-15"
   (peg-utils:exhausting-match?
    NORMAL-STAGE
    (string-trim-right (get-string-from-file "data/normal-stages/stage-3-5.txt")
                       (λ (c) (char=? c #\newline)))))

 (test-assert "normal-stages-16"
   (peg-utils:exhausting-match?
    NORMAL-STAGE
    (string-trim-right (get-string-from-file "data/normal-stages/stage-4-1.txt")
                       (λ (c) (char=? c #\newline)))))

 (test-assert "normal-stages-17"
   (peg-utils:exhausting-match?
    NORMAL-STAGE
    (string-trim-right (get-string-from-file "data/normal-stages/stage-4-2.txt")
                       (λ (c) (char=? c #\newline)))))

 (test-assert "normal-stages-18"
   (peg-utils:exhausting-match?
    NORMAL-STAGE
    (string-trim-right (get-string-from-file "data/normal-stages/stage-4-3.txt")
                       (λ (c) (char=? c #\newline)))))

 (test-assert "normal-stages-19"
   (peg-utils:exhausting-match?
    NORMAL-STAGE
    (string-trim-right (get-string-from-file "data/normal-stages/stage-4-4.txt")
                       (λ (c) (char=? c #\newline)))))

 (test-assert "normal-stages-20"
   (peg-utils:exhausting-match?
    NORMAL-STAGE
    (string-trim-right (get-string-from-file "data/normal-stages/stage-4-5.txt")
                       (λ (c) (char=? c #\newline)))))

 (test-assert "normal-stages-21"
   (peg-utils:exhausting-match?
    NORMAL-STAGE
    (string-trim-right (get-string-from-file "data/normal-stages/stage-5-1.txt")
                       (λ (c) (char=? c #\newline)))))

 (test-assert "normal-stages-22"
   (peg-utils:exhausting-match?
    NORMAL-STAGE
    (string-trim-right (get-string-from-file "data/normal-stages/stage-5-2.txt")
                       (λ (c) (char=? c #\newline)))))

 (test-assert "normal-stages-23"
   (peg-utils:exhausting-match?
    NORMAL-STAGE
    (string-trim-right (get-string-from-file "data/normal-stages/stage-5-3.txt")
                       (λ (c) (char=? c #\newline)))))

 (test-assert "normal-stages-24"
   (peg-utils:exhausting-match?
    NORMAL-STAGE
    (string-trim-right (get-string-from-file "data/normal-stages/stage-5-4.txt")
                       (λ (c) (char=? c #\newline)))))

 (test-assert "normal-stages-25"
   (peg-utils:exhausting-match?
    NORMAL-STAGE
    (string-trim-right (get-string-from-file "data/normal-stages/stage-5-5.txt")
                       (λ (c) (char=? c #\newline)))))

 (test-assert "normal-stages-all"
   (peg-utils:exhausting-match?
    NORMAL-STAGES
    (get-string-from-file "data/normal-stages/normal-stages.txt"))))


(test-group
 "stage-dat"

 (test-assert "stage-dat"
   (peg-utils:exhausting-match? STAGE-DAT (get-string-from-file "data/stage.txt"))))

(test-end "grammar-test")
